const rq = require('request-promise'),
	crypto = require('crypto'),
	WeiXinPay = require('weixinpay');

module.exports = class extends think.Service {
	/**
	 * @author: ares
	 * @date: 2018/5/25 9:49
	 * @description: 根据code获取openid和session_key
	 * @param {string}code     临时凭证
	 * @returns {*}
	 */
	getOpenIdAndSessionKey(code){
		const options = {
			method: 'GET',
			url: 'https://api.weixin.qq.com/sns/jscode2session',
			qs: {
				appid: think.config('weixin.appid'),
				secret: think.config('weixin.secret'),
				js_code: code,
				grant_type: 'authorization_code'
			},
			json:true
		};
		return rq(options);
	}

	/**
	 * @author: ares
	 * @date: 2018/5/25 10:04
	 * @description: 校验数据完整性
	 * @param {object}data   待校验的数据
	 * @param {string}sessionKey    会话密钥
	 * @returns {boolean}
	 */
	verifyDataIntegrity(data,sessionKey){
		let waitVerifyData = data.rawData + sessionKey,
		signature = crypto.createHash('sha1').update(waitVerifyData).digest('hex');
		if (data.signature === signature) {
			return true;
		}else {
			return false;
		}
	}

	/**
	 * @author: ares
	 * @date: 2018/5/25 10:18
	 * @description: 解密数据
	 * @param {object}data   待解密数据
	 * @param {string}sessionKey  回话密钥
	 * @returns {string}
	 */
	decryptData(data,sessionKey) {
		// base64 decode
		let _sessionKey = new Buffer(sessionKey, 'base64'),
			encryptedData = new Buffer(data.encryptedData, 'base64'),
			iv = new Buffer(data.iv, 'base64'),
			decoded = '';
		try {
			// 解密
			let decipher = crypto.createDecipheriv('aes-128-cbc', _sessionKey, iv);
			// 设置自动 padding 为 true，删除填充补位
			decipher.setAutoPadding(true);
			decoded = decipher.update(encryptedData, 'binary', 'utf8');
			decoded += decipher.final('utf8');
			decoded = JSON.parse(decoded);
		} catch (err) {
			return '';
		}
		if (decoded.watermark.appid !== think.config('weixin.appid')) {
			return '';
		}
		return decoded;
	}

	/**
	 * @author: ares
	 * @date: 2018/5/25 10:27
	 * @description: 创建统一下单
	 * @param {object}payInfo 发起支付时携带的信息
	 * @returns {Promise}
	 */
	createUnifiedOrder(payInfo) {
		let weixinpay = new WeiXinPay({
			appid: think.config('weixin.appid'), // 微信小程序appid
			openid: payInfo.openid, // 用户openid
			mch_id: think.config('weixin.mch_id'), // 商户帐号ID
			partner_key: think.config('weixin.partner_key') // 秘钥
		});
		return new Promise((resolve, reject) => {
			weixinpay.createUnifiedOrder({
				body: payInfo.body,
				out_trade_no: payInfo.out_trade_no,
				total_fee: payInfo.total_fee,
				spbill_create_ip: payInfo.spbill_create_ip,
				notify_url: think.config('weixin.notify_url'),
				trade_type: 'JSAPI'
			}, (res) => {
				if (res.return_code === 'SUCCESS' && res.result_code === 'SUCCESS') {
					let returnParams = {
						'appid': res.appid,
						'timeStamp': parseInt(Date.now() / 1000) + '',
						'nonceStr': res.nonce_str,
						'package': 'prepay_id=' + res.prepay_id,
						'signType': 'MD5'
					};
					let paramStr = `appId=${returnParams.appid}&nonceStr=${returnParams.nonceStr}&package=${returnParams.package}&signType=${returnParams.signType}&timeStamp=${returnParams.timeStamp}&key=` + think.config('weixin.partner_key');
					returnParams.paySign = md5(paramStr).toUpperCase();
					resolve(returnParams);
				} else {
					reject(res);
				}
			});
		});
	}

	/**
	 * @author: ares
	 * @date: 2018/5/25 10:32
	 * @description: 生成排序后的支付参数
	 * @param {object}queryObj  支付参数
	 * @returns {string}
	 */
	buildSortPayQuery(queryObj) {
		let sortPayOptions = {};
		for (let key of Object.keys(queryObj).sort()) {
			sortPayOptions[key] = queryObj[key];
		}
		let payOptionQuery = '';
		for (let key of Object.keys(sortPayOptions).sort()) {
			payOptionQuery += key + '=' + sortPayOptions[key] + '&';
		}
		payOptionQuery = payOptionQuery.substring(0, payOptionQuery.length - 1);
		return payOptionQuery;
	}

	/**
	 * @author: ares
	 * @date: 2018/5/25 10:45
	 * @description: 签名支付参数
	 * @param {string}queryStr    支付参数
	 * @returns {string}
	 */
	signPayQuery(queryStr) {
		queryStr = queryStr + '&key=' + think.config('weixin.partner_key');
		return md5(queryStr).toUpperCase();
	}

	/**
	 * @author: ares
	 * @date: 2018/5/25 10:47
	 * @description: 处理支付回调
	 * @param {object}notifyData  待处理数据
	 * @returns {*}
	 */
	payCallBack(notifyData) {
		if (think.isEmpty(notifyData)) {
			return false;
		}
		let notifyObj = {},
			sign = '';
		for (let key of Object.keys(notifyData)) {
			if (key !== 'sign') {
				notifyObj[key] = notifyData[key][0];
			} else {
				sign = notifyData[key][0];
			}
		}
		if (notifyObj.return_code !== 'SUCCESS' || notifyObj.result_code !== 'SUCCESS') {
			console.log('return_code false');
			return false;
		}
		let signString = this.signPayQuery(this.buildSortPayQuery(notifyObj));
		if (think.isEmpty(sign) || signString !== sign) {
			return false;
		}
		return notifyObj;
	}
};
